﻿
#region Usings
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using FasterWPF.Selectors;
#endregion

namespace FasterWPF
{
    //#region Support for Extension Methods in IronPython
    //[assembly: Microsoft.Scripting.Runtime.ExtensionType(
    //typeof(string),
    //typeof(FasterWPF.CommonExt)
    //)]

    //[assembly: Microsoft.Scripting.Runtime.ExtensionType(
    //typeof(System.Windows.Window), 
    //typeof(FasterWPF.CommonExt)
    //)]
    //#endregion

    public static partial class CommonExt
    {       
        //DEVELOPER NOTES
        //
        //CHAIN
        //Container Type GRID is composed of:    Border - Content Control - GRID
        //Container Type PANEL is composed of:   Border - Content Control - STACKPANEL(Horizontal)

        //TAGS
        //Note that the Parent is stored in the Tag of the ContentControl in the chain: Border - Content Control - Tag - Parent

        //DICTIONARIES

        //1. SETTINGS DICTIONARY
        //The Parent Container's Tag property contains a Dictionary for storing properties/settings. If you are looking for it in the debugger, it is at the FrameworkElement level of the Parent [FrameworkElement.Tag]
        
        //2. COMPOSITE_LOOKUP DICTIONARY
        //["CompositeLookup"] Dictionary is another dictionary stored inside the main one that also contains all rows (Borders) by key, e.g. guid

        //3. CHILD_LOOKUP DICTIONARY
        //["ChildLookup"] Dictionary is another dictionary stored inside the main one that also contains all elements by fine-grained key, e.g. guid_0_1       

        //4. DISPOSABLES DICTIONARY
        //["DisposablesDictionary"] Dictionary is another dictionary stored inside the main one that also contains all the IDisposables (either an EventDisposer OR an Rx Disposable) for unsubscribing events

        //5. ORDERED KEY LIST
        //Added a new OrderedKeyList to store all the keys in order added in a List<string>.

        //6. ATTACHED PROPERTIES DICTIONARY
        //["AttachedPropertiesDict"] Dictionary is another dictionary stored inside the main one that also contains all settings that are to be applied as Attached Properties

        //7. ATTACHED PROPERTIES BY ROWCOL DICTIONARY
        //["AttachedPropertiesByRowColDict"] Dictionary is another dictionary stored inside the main one that also contains all settings that are to be applied as Attached Properties

        //NOTE: you can FIND each spot in code where items are added to these dictionaries
        //by doing a FIND on the string "ADD_TO_DICTIONARY BOOKMARK"
        // you can FIND each spot in code where items are removed from these dictionaries
        //by doing a FIND on the string "REMOVE_FROM_DICTIONARY BOOKMARK"

        #region Key and Dictionary Support

        /// <summary>
        /// Get a dictionary that contains all child FrameworkElements by fine-grained key, e.g. guid_0_1  
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static System.Collections.Generic.Dictionary<string, object> GetChildLookupDictionary<T>(this T source)
          where T : FrameworkElement
        {
            var ChildLookup = (Dictionary<string, object>)(source.GetSettingsDictionary())["ChildLookup"];

            return ChildLookup;
        }

        /// <summary>
        /// Get Parent from a Child Framework Element inside a Composite, e.g. from a TextBox or Image
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="childElement"></param>
        /// <returns></returns>
        public static T GetParentFromChildElement<T>(this FrameworkElement childElement)  
           where T : FrameworkElement
        {
            return (T)(childElement.GetBorderFromChildElement<T>().Cast<Border>().Child.Cast<ContentControl>().GetParentFromContentControlOfComposite<T>());
        }

        /// <summary>
        /// Get Border of composite from a Child Framework Element, e.g. from a TextBox or Image
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="childElement"></param>
        /// <returns></returns>
        public static object GetBorderFromChildElement<T>(this FrameworkElement childElement)
            where T: FrameworkElement
        {
            IComposite icomp = FasterWPF.CompositeTypeHelper.GetICompositeFromChild(childElement);            
            return (Border)icomp.GetBorder<T>(childElement);
        }

        /// <summary>
        /// Get Border of composite from the Child StackPanel that contains the container, e.g. that contains Grid of a GridComposite
        /// </summary>
        /// <param name="sender"></param>
        /// <returns></returns>
        public static Border GetBorderFromChildStackPanel(this StackPanel sender)
        {
            Border bdr = null;

            if (sender is StackPanel)
            {
                bdr = (Border)((ContentControl)((StackPanel)(sender.Parent)).Parent).Parent;
            }

            return bdr;
        }

        /// <summary>
        ///  Get Parent T of a composite from the Child StackPanel that contains the container, e.g. that contains Grid of a GridComposite
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sender"></param>
        /// <returns></returns>
        public static T GetTFromChildContentControl<T>(this ContentControl sender)
    where T : FrameworkElement
        {
            T lbx = default(T);

            if (sender is ContentControl)
            {
                lbx = (T)((ContentControl)sender).GetParentFromContentControlOfComposite<T>();
            }

            return lbx;
        }

        /// <summary>
        /// Get fine-grained child keys (e.g. guid_0_1) from Child Lookup Dictionary that match based on composite key (e.g. guid)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static List<string> GetChildKeysFromComposite<T>(this T chain, string key)
             where T : FrameworkElement
        {
            char underscoreChar = '_';
            var matchingKeys = new List<string>();
            var keyDictionary = GetChildLookupDictionary(chain);

            foreach (var keyItem in keyDictionary)
            {
                if (keyItem.Key.Split(underscoreChar)[0] == key)
                {
                    matchingKeys.Add(keyItem.Key);
                }
            }

            return matchingKeys;
        }

        /// <summary>
        /// Get children from inside composite based on composite key (e.g. guid)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static List<object> GetChildrenFromComposite<T>(this T chain, string key)
             where T : FrameworkElement
        {
            char underscoreChar = '_';
            var matchingObjects = new List<object>();
            var keyDictionary = GetChildLookupDictionary(chain);

            foreach (var keyItem in keyDictionary)
            {
                if (keyItem.Key.Split(underscoreChar)[0] == key)
                {
                    matchingObjects.Add(keyItem.Value);
                }
            }

            return matchingObjects;
        }

        /// <summary>
        /// Get the container K (e.g. Grid if a GridComposite) from a composite (with a parent T)
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="composite"></param>
        /// <returns></returns>
        public static K GetContainerFromComposite<K, T>(this T chain, Border composite)
            where T : FrameworkElement
            where K : FrameworkElement
        {
            IComposite icomp1 = SettingsManager.GetIComposite<T>(chain);
            return icomp1.GetContainer<K>(composite);
        }

        /// <summary>
        /// Get the container K (e.g. Grid if a GridComposite) from a composite by key
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static K GetContainerFromComposite<K, T>(this T chain, string key)
            where T : FrameworkElement
            where K : FrameworkElement
        {
            IComposite icomp1 = SettingsManager.GetIComposite<T>(chain);

            return icomp1.GetContainer<K>(chain.GetCompositeFromParent<T>(key));
        }

        /// <summary>
        /// Get Parent from Composite, a.k.a from the Border that is the root of the Composite
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sender"></param>
        /// <returns></returns>
        public static T GetParentFromComposite<T>(this Border composite)
          where T : FrameworkElement
        {
            T ChildLookup = (T)(composite.Child.Cast<ContentControl>().GetParentFromContentControlOfComposite<T>());

            return ChildLookup;
        }

        /// <summary>
        /// Get Child Lookup Dictionary of Parent from an individual Composite. Child Lookup Dictionary contains all children from all composites in the parent.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sender"></param>
        /// <returns></returns>
        public static System.Collections.Generic.Dictionary<string, object> GetChildLookupDictionaryFromComposite<T>(this Border sender)
                  where T : FrameworkElement
        {
            var ChildLookup = (Dictionary<string, object>)((Dictionary<string, object>)((T)(sender.Cast<Border>().Child.Cast<ContentControl>().Tag)).Tag)["ChildLookup"];

            return ChildLookup;
        }
       
        /// <summary>
        /// Get Child K at X-Y (row, column) from Composite using IComposite method (rather than Child Lookup Dictionary)
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public static K GetChildFromComposite<K, T>(this Border source, int row, int column)
            where K : UIElement
            where T : FrameworkElement
        {        
            return source.Child.Cast<ContentControl>().GetElement<K, T>(row, column);
        }

        /// <summary>
        /// Get Child K at X-Y (row, column) from Composite using Child Lookup Dictionary
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="key"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public static K GetChildViaLookupDictionary<K, T>(this T source, string key, int row, int column)
            where K : UIElement
            where T : FrameworkElement
        {
            object tempResult = null;
            source.GetCompositeFromParent(key).GetChildLookupDictionaryFromComposite<T>().TryGetValue(( key + "_" + row + "_" + column ) as string, out tempResult);

            return tempResult as K;
        }

        /// <summary>
        ///  Get Child FrameworkElement at X-Y (row, column) from Composite using IComposite method (rather than Child Lookup Dictionary)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public static FrameworkElement GetFrameworkElementFromComposite<T>(this Border source, int row, int column)
            where T : FrameworkElement
        {
            return source.Child.Cast<ContentControl>().GetFrameworkElement<T>(row, column);
        }

        /// <summary>
        /// Check if Child K exists at X-Y (row, column) on Composite looking up via Child Lookup Dictionary
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public static bool IsChildOnComposite<K, T>(this Border source, int row, int column)
            where K : UIElement
            where T : FrameworkElement
        {
            Dictionary<string, object> childLookup = source.GetParentFromComposite<T>().GetChildLookupDictionary<T>();

            bool retVal = false;
            string row_col = "_" + row + "_" + column;
            string fullKey = source.GetKey() + row_col;
            if (childLookup.Keys.Contains(fullKey) && (childLookup[fullKey] is K))
            {
                retVal = true;
            }
            else
            {
                retVal = false;
            }

            return retVal;
        }

        /// <summary>
        /// Get Child from Parent based on Key (guid) and X-Y (row, column)
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="key"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public static K GetChildFromParent<K, T>(this T source, string key, int row, int column)
            where K : UIElement
            where T : FrameworkElement
        {
            return source.GetCompositeFromParent<T>(key).Child.Cast<ContentControl>().GetElement<K, T>(row, column);
        }

        /// <summary>
        /// Check if Composite exists on Parent based on Key (guid). Key cannot be null. 
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool IsCompositeOnParent<T>(this T source, string key)
            where T : FrameworkElement
        {
            Dictionary<string, object> CompositeLookup = (Dictionary<string, object>)(source.GetSettingsDictionary())["CompositeLookup"];

            bool retVal = false;
            object value = null;

            if(key!=null)
            {
                if (CompositeLookup.TryGetValue(key, out value))
                {
                    retVal = true;
                }
                else
                {
                    retVal = false;
                }
            }
            else
            {
                throw new KeyNullException("Composite key cannot be null!");
            }

            return retVal;
        }

        /// <summary>
        /// Get Composite from Parent based on Key (guid). Key cannot be null. If Key not found, an exception will be thrown.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static Border GetCompositeFromParent<T>(this T source, string key)
          where T : FrameworkElement
        {
            return GetCompositeFromCompositeLookupDictionary<T>(source, key);
        }

        /// <summary>
        /// Get Composite from Parent via Composite Lookup Dictionary based on Key (guid). Key cannot be null. If Key not found, an exception will be thrown.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static Border GetCompositeFromCompositeLookupDictionary<T>(this T source, string key)
            where T : FrameworkElement
        {
            Dictionary<string, object> CompositeLookup = (Dictionary<string, object>)(source.GetSettingsDictionary())["CompositeLookup"];

            Border retVal = null;
            object outVal = null;

            if(key!=null)
            {
                if (CompositeLookup.TryGetValue(key, out outVal))
                {
                    retVal = (Border)outVal;
                } 
                else
                {
                    throw new CompositeKeyNotFoundException("No composite could be found with that key in this parent!", key);
                }
            }
            else
            {
                throw new KeyNullException("Composite key cannot be null!");
            }

            return retVal;
        }

        /// <summary>
        ///  Get dictionary from Parent that contains all Composites (Borders) stored by key, e.g. guid
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Dictionary<string, object> GetCompositeLookupDictionary<T>(this T source)
                  where T : FrameworkElement
        {
            Dictionary<string, object> CompositeLookup = (Dictionary<string, object>)(source.GetSettingsDictionary())["CompositeLookup"];

            return CompositeLookup;
        }

        /// <summary>
        /// Get dictionary from Parent by way of Composite that contains all Composites (Borders) stored by key, e.g. guid
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sender"></param>
        /// <returns></returns>
        public static Dictionary<string, object> GetCompositeLookupDictionaryFromComposite<T>(object sender)
where T : FrameworkElement
        {
            Dictionary<string, object> CompositeLookup = (Dictionary<string, object>)((Dictionary<string, object>)((T)sender.Cast<Border>().Child.Cast<ContentControl>().Tag).Tag)["CompositeLookup"];

            return CompositeLookup;
        }

        /// <summary>
        /// Get list of Composite Keys (guids) from Parent. List of Keys is in order that they were added.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static List<String> GetOrderedKeyList<T>(this T source)
where T : FrameworkElement
        {
            return (List<String>)source.GetSettingsDictionary()["KeyList"];
        }

        /// <summary>
        /// Get Key (guid) of Composite (Border)
        /// </summary>
        /// <param name="sender"></param>
        /// <returns></returns>
        public static string GetKey(this Border sender)
        {
            string retVal = null;

            Dictionary<string, object> CompositeLookup = CommonExt.GetCompositeLookupDictionaryFromComposite<FrameworkElement>(sender);

            System.Collections.Generic.KeyValuePair<string, object> ibe = CompositeLookup.Where(row =>
            {
                if (row.Value == sender) { return true; } else { return false; }
            }).First();

            retVal = ibe.Key.ToString();

            return retVal;
        }

        /// <summary>
        /// Get Key (guid) of Composite (Border) where it is passed in as type object (sender).
        /// </summary>
        /// <param name="e"></param>
        /// <param name="sender"></param>
        /// <returns></returns>
        public static string GetKey(this MouseButtonEventArgs e, object sender)
        {
            string retVal = null;

            Dictionary<string, object> CompositeLookup = CommonExt.GetCompositeLookupDictionaryFromComposite<FrameworkElement>(sender);

            System.Collections.Generic.KeyValuePair<string, object> ibe = CompositeLookup.Where(row =>
            {
                if (row.Value == sender) { return true; } else { return false; }
            }).First();

            retVal = ibe.Key.ToString();

            return retVal;
        }

        /// <summary>
        /// Add key and IDisposable (value) to the Disposables Dictionary that is passed-in
        /// </summary>
        /// <param name="key"></param>
        /// <param name="evd"></param>
        /// <param name="eventsList"></param>
        public static void AddToDisposablesDictionary(string key, IDisposable evd, Dictionary<string, IDisposable> eventsList)
        {
            //ADD_TO_DICTIONARY BOOKMARK - 4. Disposables
            eventsList.Add(key, evd);
        }

        /// <summary>
        /// Get dictionary of subscribed child events from Parent. Disposing event unsubscribes the event.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <returns></returns>
        public static System.Collections.Generic.Dictionary<string, System.IDisposable> GetDisposablesDictionary<T>(this T chain)
            where T : FrameworkElement
        {
            Dictionary<string, IDisposable> eventsDict = (Dictionary<string, IDisposable>)((Dictionary<string,
object>)chain.Tag)["DisposablesDictionary"];
            return eventsDict;
        }

        /// <summary>
        /// Get dictionary that contains all settings that are to be applied as Attached Properties
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <returns></returns>
        public static System.Collections.Generic.Dictionary<string, object> GetAttachedPropertiesDictionary<T>(this T chain)
            where T : FrameworkElement
        {
            Dictionary<string, object> eventsDict = (Dictionary<string, object>)((Dictionary<string,
object>)chain.Tag)["AttachedPropertiesDict"];
            return eventsDict;
        }

        /// <summary>
        /// Get dictionary stored inside the main one that also contains all settings that are to be applied as Attached Properties by X-Y (row, column)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <returns></returns>
        public static System.Collections.Generic.Dictionary<string, object> GetAttachedPropertiesByRowColDictionary<T>(this T chain)
    where T : FrameworkElement
        {
            Dictionary<string, object> eventsDict = (Dictionary<string, object>)((Dictionary<string,
object>)chain.Tag)["AttachedPropertiesByRowColDict"];
            return eventsDict;
        }
        
        /// <summary>
        /// Get dictionary of subscribed child events from Border. Disposing event unsubscribes the event.
        /// </summary>
        /// <param name="chain"></param>
        /// <returns></returns>
        public static System.Collections.Generic.Dictionary<string, System.IDisposable> GetDisposablesDictionaryFromBorder(this Border chain)
        {
            Dictionary<string, object> settings = (Dictionary<string, object>)((FrameworkElement)(chain.Cast<Border>().Child.Cast<ContentControl>()).Tag).Tag;

            Dictionary<string, IDisposable> eventsList = (Dictionary<string, IDisposable>)settings["DisposablesDictionary"];
            return eventsList;
        }
        
        #endregion

        #region Add Anything, Add Existing and Apply Settings

        public static ContentControl AddAnything<K, T>(this ContentControl chain, string key, int row, int col)
            where T : FrameworkElement
            where K : FrameworkElement, new()
        {
            T lbx = ((ContentControl)chain).GetParentFromContentControlOfComposite<T>();
            Dictionary<string, object> settings = lbx.GetSettingsDictionary();
            string row_col = row + "_" + col;
            string fullKey = key + "_" + row_col;

            K objToAdd = new K();

            addCommon<K, T>(chain, row, col, lbx, settings, fullKey, objToAdd);

            return chain;
        }
        
        public static ContentControl AddAnyIParent<K, T>(this ContentControl chain, string key, int row, int col, Action<K> initializeIParent)
            where T : FrameworkElement
            where K : FrameworkElement, new()
        {
            K newIParent = new K();
            initializeIParent(newIParent);

            T lbx = ((ContentControl)chain).GetParentFromContentControlOfComposite<T>();
            Dictionary<string, object> settings = lbx.GetSettingsDictionary();
            string row_col = row + "_" + col;
            string fullKey = key + "_" + row_col;

            addCommon<K, T>(chain, row, col, lbx, settings, fullKey, newIParent);

            return chain;
        }

        public static ContentControl AddExisting<K, T>(this ContentControl chain, string key, int row, int col, K objToAdd)
            where T : FrameworkElement
            where K : FrameworkElement, new()
        {
            T lbx = ((ContentControl)chain).GetParentFromContentControlOfComposite<T>();
            Dictionary<string, object> settings = lbx.GetSettingsDictionary();
            string row_col = row + "_" + col;
            string fullKey = key + "_" + row_col;

            addCommon<K, T>(chain, row, col, lbx, settings, fullKey, objToAdd);

            return chain;
        }

        private static Panel addCommon<K, T>(ContentControl chain, int row, int col, T source, Dictionary<string, object> settings, string fullKey, K objToAdd)
            where K : FrameworkElement, new()
            where T : FrameworkElement
        {
            CompositeTypeHelper.ApplySettingsForChild<K>(settings, objToAdd);
            CompositeTypeHelper.ApplySettingsForChildAtRowCol(settings, row, col, objToAdd);
            CompositeTypeHelper.ApplyAnyAttachedProperties<T, K>(source, settings, objToAdd);
            CompositeTypeHelper.ApplyAnyAttachedPropertiesByRowCol<T, K>(source, settings, row, col, objToAdd);

            //ADD_TO_DICTIONARY BOOKMARK - 3. ChildLookup
             source.GetChildLookupDictionary().Add(fullKey, objToAdd);

            IComposite icomp = SettingsManager.GetIComposite<T>(source);
            return icomp.AddChild<T>(source, chain, row, col, objToAdd);
        }
               
       #endregion        
                
        #region Add Text and Apply Settings

        public static ContentControl AddText<T>(this ContentControl chain, string key, int row, int col, string newText)
             where T : FrameworkElement
        {
            return commonAddTextMethod<T>(chain, key, row, col, newText, false);
        }

        public static ContentControl AddTextWithToolTipEnabled<T>(this ContentControl chain, string key, int row, int col, string newText)
             where T : FrameworkElement
        {
            return commonAddTextMethod<T>(chain, key, row, col, newText, true);
        }

        private static ContentControl commonAddTextMethod<T>(ContentControl chain, string key, int row, int col, string newText, bool includeToolTip)
             where T : FrameworkElement
        {
            T source = ((ContentControl)chain).GetParentFromContentControlOfComposite<T>();

            IComposite icomp = SettingsManager.GetIComposite<T>(source);

            Run xRun = null;
            string row_col = row + "_" + col;
            string fullKey = key + "_" + row_col;

            Dictionary<string, object> settings = source.GetSettingsDictionary();

            xRun = new Run(newText);
            TextBlock txb = new TextBlock(xRun);
            
            Panel p = addCommon<TextBlock, T>(chain, row, col, source, settings, fullKey, txb);
            
            if (includeToolTip)
            {
                CommonExt.addIsMouseOverTriggerAndBindToolTipToRun(typeof(Panel), xRun, p);
            }
            
            return chain;
        }

        private static void addIsMouseOverTriggerAndBindToolTipToRun(Type tpe, Run xRun, Panel p)
        {
            Style style = new Style(tpe, p.Style);

            Trigger t = new Trigger();
            t.Property = Control.IsMouseOverProperty;
            t.Value = true;

            Setter setter = new Setter();
            setter.Property = Control.ToolTipProperty;
            setter.Value = new Binding
            {
                Source = xRun,
                Path = new PropertyPath(Run.TextProperty)
            };

            t.Setters.Add(setter);
            style.Triggers.Add(t);

            p.Style = style;
        }
        
        public static void SetMouseOverColorOnContainer<C, T>(this ContentControl chain, Brush brush)
            where C : FrameworkElement
            where T : FrameworkElement
        {
            T source = chain.GetTFromChildContentControl<T>();
            IComposite icomp = SettingsManager.GetIComposite<T>(source);

            C container = (C)icomp.GetContainerFromChildContentControl<C>(chain);

            Style style = new Style(typeof(C), container.Style);
            Trigger t = new Trigger();
            t.Property = FrameworkElement.IsMouseOverProperty;
            t.Value = true;
            Setter setter = new Setter();
            setter.Property = Panel.BackgroundProperty;
            setter.Value = brush;
            t.Setters.Add(setter);

            style.Triggers.Add(t); // Important: add a trigger before applying style
            container.Style = style;
        }

        //need a databinding version . . . with trigger support
        //public static void SetMouseOverColorOnContainer<C, T>(this ContentControl chain, Brush brush)
        //    where C : FrameworkElement
        //    where T : FrameworkElement
        //{
        //    T source = chain.GetTFromChildContentControl<T>();
        //    IComposite icomp = SettingsManager.GetIComposite<T>(source);

        //    C container = (C)icomp.GetContainerFromChildContentControl<C>(chain);

        //    Style style = new Style(typeof(C), container.Style);
        //    Trigger t = new Trigger();
        //    t.Property = FrameworkElement.IsMouseOverProperty;
        //    t.Value = true;
        //    Setter setter = new Setter();
        //    setter.Property = Panel.BackgroundProperty;
        //    setter.Value = brush;
        //    t.Setters.Add(setter);

        //    style.Triggers.Add(t); // Important: add a trigger before applying style
        //    container.Style = style;
        //}
        
        public static void SetColorOnContainer<C, T>(this ContentControl chain, Brush brush)
            where C : FrameworkElement
            where T : FrameworkElement
        {
            T source = chain.GetTFromChildContentControl<T>();
            IComposite icomp = SettingsManager.GetIComposite<T>(source);

            C container = (C)icomp.GetContainerFromChildContentControl<C>(chain);

            Style style = new Style(typeof(C), container.Style);
            Setter setter = new Setter();
            setter.Property = Panel.BackgroundProperty;
            setter.Value = brush;
            style.Setters.Add(setter);

            container.Style = style;
        }
        #endregion

        #region Add Image and Apply Settings

        public static ContentControl AddImage<T>(this ContentControl chain, string key, int row, int col, string imageUri, UriKind uriKind, double imageWidth, int rowSpan, int colSpan)
                     where T : FrameworkElement
        {
            commonAddImageMethod<T>(chain, key, row, col, imageUri, uriKind, imageWidth, rowSpan, colSpan);

            return chain;
        }

        public static ContentControl AddImage<T>(this ContentControl chain, string key, int row, int col, string imageUri, UriKind uriKind, double imageWidth)
                     where T : FrameworkElement
        {
            commonAddImageMethod<T>(chain, key, row, col, imageUri, uriKind, imageWidth, 1, 1);

            return chain;
        }

        private static void commonAddImageMethod<T>(ContentControl chain, string key, int row, int col, string imageUri, UriKind uriKind, double imageWidth, int rowSpan, int colSpan)
                     where T : FrameworkElement
        {
            T lbx = ((ContentControl)chain).GetParentFromContentControlOfComposite<T>();
            Dictionary<string, object> settings = lbx.GetSettingsDictionary();
            string row_col = row + "_" + col;
            string fullKey = key + "_" + row_col;

            IComposite icomp = SettingsManager.GetIComposite<T>(lbx);

            Image finalImage = new Image();
            finalImage.Width = imageWidth;

            var uriSource = new Uri(imageUri, uriKind);
            var myImage = new BitmapImage(uriSource);
            myImage.Freeze();
            finalImage.Source = myImage;

            if (icomp.IsGrid())
            {
                Grid.SetRowSpan(finalImage, rowSpan);
                Grid.SetColumnSpan(finalImage, colSpan);
            }
            
            addCommon<Image, T>(chain, row, col, lbx, settings, fullKey, finalImage);
        }

        public static ContentControl AddGeometry<T>(this ContentControl chain, string key, int row, int col, Brush background, Pen pen, Geometry geometry, double imageWidth, int rowSpan, int colSpan)
                     where T : FrameworkElement
        {
            commonAddGeometryMethod<T>(chain, key, row, col, background, pen, geometry, imageWidth, rowSpan, colSpan);

            return chain;
        }

        public static ContentControl AddGeometry<T>(this ContentControl chain, string key, int row, int col, Brush background, Pen pen, Geometry geometry, double imageWidth)
                     where T : FrameworkElement
        {
            commonAddGeometryMethod<T>(chain, key, row, col, background, pen, geometry, imageWidth, 1, 1);

            return chain;
        }

        private static void commonAddGeometryMethod<T>(ContentControl chain, string key, int row, int col, Brush background, Pen pen, Geometry geometry, double imageWidth, int rowSpan, int colSpan)
             where T : FrameworkElement
        {
            T lbx = ((ContentControl)chain).GetParentFromContentControlOfComposite<T>();
            Dictionary<string, object> settings = lbx.GetSettingsDictionary();
            string row_col = row + "_" + col;
            string fullKey = key + "_" + row_col;

            IComposite icomp = SettingsManager.GetIComposite<T>(lbx);

            Image finalImage = new Image();
            finalImage.Width = imageWidth;
           
            DrawingImage di = new DrawingImage();
            GeometryDrawing gtd = new GeometryDrawing();
            gtd.Brush = background;
            gtd.Pen = pen;
            gtd.Geometry = geometry;
            di.Drawing = gtd;
          
            finalImage.Source = di;

            if (icomp.IsGrid())
            {
                Grid.SetRowSpan(finalImage, rowSpan);
                Grid.SetColumnSpan(finalImage, colSpan);
            }

            addCommon<Image, T>(chain, row, col, lbx, settings, fullKey, finalImage);
        }
        
        #endregion

        #region Begin Composite . . . End Composite Syntax    
                
        /// <summary>
        /// Start of a BeginComposite...EndComposite chain of methods used to build a Composite. This method automatically creates a GUID to identify the Composite.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <returns></returns>
        public static InnerChain<T> BeginComposite<T>(this T chain)
        {
            string key = Guid.NewGuid().ToString();
            List<Func<ContentControl, ContentControl>> startList = new List<Func<ContentControl, ContentControl>>();
            InnerChain<T> parm = new InnerChain<T>(chain, key, startList);
            return parm;
        }
        
        /// <summary>
        /// Start of a BeginComposite...EndComposite chain of methods used to build a Composite. Key parameter is used to identify the Composite; typically, this may be a GUID.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static InnerChain<T> BeginComposite<T>(this T chain, string key)
        {
            List<Func<ContentControl, ContentControl>> startList = new List<Func<ContentControl, ContentControl>>();
            InnerChain<T> parm = new InnerChain<T>(chain, key, startList);
            return parm;
        }
        
        /// <summary>
        /// End of a BeginComposite...EndComposite chain of methods used to build a Composite. Args may define more properties related to Composite, else just set to null.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="chain"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static Border EndComposite<T, K>(this InnerChain<T> chain, K args)
where T : FrameworkElement
        {
            return chain.Item1.AddComposite<T, K>(chain.Item2, args, container =>
            {
                foreach (Func<ContentControl, ContentControl> f in chain.Item3)
                {
                    f(container);
                }
            });
        }

        /// <summary>
        /// End of a BeginComposite...EndComposite chain of methods used to build a Composite. OverrideGridSettings allows specifying Grid Settings unique to this Composite.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="chain"></param>
        /// <param name="args"></param>
        /// <param name="overrideGridSettings"></param>
        /// <returns></returns>
        public static Border EndComposite<T, K>(this InnerChain<T> chain, K args, object overrideGridSettings)    
where T : FrameworkElement
        {
            return chain.Item1.AddComposite<T, K>(chain.Item2, args, overrideGridSettings, container =>
            {
                foreach (Func<ContentControl, ContentControl> f in chain.Item3)
                {
                    f(container);
                }
            });
        }

        /// <summary>
        /// Add an existing FrameworkElement of type K to the Composite at X-Y (row, column)
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="objToAdd"></param>
        /// <returns></returns>
        public static InnerChain<T> AddExisting<K, T>(this InnerChain<T> chain, int row, int col, K objToAdd)
            where T : FrameworkElement
            where K : FrameworkElement, new()
        {
            chain.Item3.Add(((container) =>
            {
                return container.AddExisting<K, T>(chain.Item2, row, col, objToAdd);
            }));

            return chain;
        }

        /// <summary>
        /// Add a new IParent of type K to the Composite at X-Y (row, column). This IParent can then add on its own Composites.
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="initializeIParent"></param>
        /// <returns></returns>
        public static InnerChain<T> AddAnyIParent<K, T>(this InnerChain<T> chain, int row, int col, Action<K> initializeIParent)
            where T : FrameworkElement
            where K : FrameworkElement, new()
        {           
            chain.Item3.Add(((container) =>
            {
                return container.AddAnyIParent<K, T>(chain.Item2, row, col, initializeIParent);
            }));

            return chain;
        }    

        /// <summary>
        /// Automatically instantiates a FrameworkElement of type K and adds it to the Composite at X-Y (row, column)
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <returns></returns>
        public static InnerChain<T> AddAnything<K, T>(this InnerChain<T> chain, int row, int col)
            where T : FrameworkElement
            where K : FrameworkElement, new()
        {
            chain.Item3.Add(((container) =>
            {
                return container.AddAnything<K, T>(chain.Item2, row, col);
            }));
            return chain;
        }

        /// <summary>
        /// Add Label to the Composite at X-Y (row, column)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="newText"></param>
        /// <param name="newBrush"></param>
        /// <returns></returns>
        public static InnerChain<T> AddLabel<T>(this InnerChain<T> chain, int row, int col, string newText, Brush backgroundBrush)
where T : FrameworkElement
        {
            Label myLabel = new Label();
            myLabel.Content = newText;
            myLabel.Background = backgroundBrush;

            chain.Item3.Add(((container) =>
            {
                return container.AddExisting<Label, T>(chain.Item2, row, col, myLabel);
            }));
            return chain;
        }

        /// <summary>
        /// Add Label to the Composite at X-Y (row, column)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="newText"></param>
        /// <param name="newBrush"></param>
        /// <returns></returns>
        public static InnerChain<T> AddLabel<T>(this InnerChain<T> chain, int row, int col, string newText, Brush backgroundBrush, Brush foregroundBrush)
where T : FrameworkElement
        {
            Label myLabel = new Label();
            myLabel.Content = newText;
            myLabel.Background = backgroundBrush;
            myLabel.Foreground = foregroundBrush;

            chain.Item3.Add(((container) =>
            {
                return container.AddExisting<Label, T>(chain.Item2, row, col, myLabel);
            }));
            return chain;
        }

        /// <summary>
        /// Add Label to the Composite at X-Y (row, column), also specifying width and height
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="newText"></param>
        /// <param name="newBrush"></param>
        /// <returns></returns>
        public static InnerChain<T> AddLabel<T>(this InnerChain<T> chain, int row, int col, double width, double height, string newText, Brush backgroundBrush)
    where T : FrameworkElement
        {
            Label myLabel = new Label();
            myLabel.Width = width;
            myLabel.Height = height;
            myLabel.Content = newText;
            myLabel.Background = backgroundBrush;

            chain.Item3.Add(((container) =>
            {
                return container.AddExisting<Label, T>(chain.Item2, row, col, myLabel);
            }));
            return chain;
        }
        
        /// <summary>
        /// Add Label to the Composite at X-Y (row, column) Setting the Background Brush Via a Style
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="newText"></param>
        /// <param name="newBrush"></param>
        /// <returns></returns>
        public static InnerChain<T> AddLabelSettingBackgroundViaStyle<T>(this InnerChain<T> chain, int row, int col, string newText, Brush backgroundBrush)
where T : FrameworkElement
        {
            Label myLabel = new Label();
            myLabel.Content = newText;
            myLabel.SetStyle(typeof(Label), Label.BackgroundProperty, backgroundBrush);

            chain.Item3.Add(((container) =>
            {
                return container.AddExisting<Label, T>(chain.Item2, row, col, myLabel);
            }));
            return chain;
        }

        /// <summary>
        /// Add Label to the Composite at X-Y (row, column) Setting the Background Brush Via a Style
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="newText"></param>
        /// <param name="newBrush"></param>
        /// <returns></returns>
        public static InnerChain<T> AddLabelSettingBackgroundViaStyle<T>(this InnerChain<T> chain, int row, int col, string newText, Brush backgroundBrush, Brush foregroundBrush)
where T : FrameworkElement
        {
            Label myLabel = new Label();
            myLabel.Content = newText;
            myLabel.SetStyle(typeof(Label), Label.BackgroundProperty, backgroundBrush);
            myLabel.Foreground = foregroundBrush;

            chain.Item3.Add(((container) =>
            {
                return container.AddExisting<Label, T>(chain.Item2, row, col, myLabel);
            }));
            return chain;
        }

        /// <summary>
        /// Add Label to the Composite at X-Y (row, column), also specifying width and height Setting the Background Brush Via a Style
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="newText"></param>
        /// <param name="newBrush"></param>
        /// <returns></returns>
        public static InnerChain<T> AddLabelSettingBackgroundViaStyle<T>(this InnerChain<T> chain, int row, int col, double width, double height, string newText, Brush backgroundBrush)
    where T : FrameworkElement
        {
            Label myLabel = new Label();
            myLabel.Width = width;
            myLabel.Height = height;
            myLabel.Content = newText;
            myLabel.SetStyle(typeof(Label), Label.BackgroundProperty, backgroundBrush);

            chain.Item3.Add(((container) =>
            {
                return container.AddExisting<Label, T>(chain.Item2, row, col, myLabel);
            }));
            return chain;
        }
        
        /// <summary>
        /// Add text as a Run set on the Inlines collection of a TextBlock to the Composite at X-Y (row, column)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="newText"></param>
        /// <returns></returns>
        public static InnerChain<T> AddText<T>(this InnerChain<T> chain, int row, int col, string newText)
            where T : FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                return container.AddText<T>(chain.Item2, row, col, newText);
            }));
            return chain;
        }





        /// <summary>
        /// Add Image to the Composite at X-Y (row, column)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="imageUri"></param>
        /// <param name="uriKind"></param>
        /// <param name="imageWidth"></param>
        /// <returns></returns>
        public static InnerChain<T> AddImage<T>(this InnerChain<T> chain, int row, int col, string imageUri, UriKind uriKind, double imageWidth)
    where T : FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                return container.AddImage<T>(chain.Item2, row, col, imageUri, uriKind, imageWidth);
            }));
            return chain;
        }

        /// <summary>
        /// Add Image to the Composite at X-Y (row, column), also specifying RowSpan and ColumnSpan for use in a Grid
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="imageUri"></param>
        /// <param name="uriKind"></param>
        /// <param name="imageWidth"></param>
        /// <param name="rowSpan"></param>
        /// <param name="colSpan"></param>
        /// <returns></returns>
        public static InnerChain<T> AddImage<T>(this InnerChain<T> chain, int row, int col, string imageUri, UriKind uriKind, double imageWidth, int rowSpan, int colSpan)
             where T : FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                return container.AddImage<T>(chain.Item2, row, col, imageUri, uriKind, imageWidth, rowSpan, colSpan);
            }));
            return chain;
        }

        /// <summary>
        /// Add Geometry to the Composite at X-Y (row, column)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="imageUri"></param>
        /// <param name="uriKind"></param>
        /// <param name="imageWidth"></param>
        /// <returns></returns>
        public static InnerChain<T> AddGeometry<T>(this InnerChain<T> chain, int row, int col, Brush background, Pen pen, Geometry geometry, double imageWidth)
    where T : FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                return container.AddGeometry<T>(chain.Item2, row, col, background, pen, geometry, imageWidth);
            }));
            return chain;
        }

        /// <summary>
        /// Add Geometry to the Composite at X-Y (row, column), also specifying RowSpan and ColumnSpan for use in a Grid
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="imageUri"></param>
        /// <param name="uriKind"></param>
        /// <param name="imageWidth"></param>
        /// <param name="rowSpan"></param>
        /// <param name="colSpan"></param>
        /// <returns></returns>
        public static InnerChain<T> AddGeometry<T>(this InnerChain<T> chain, int row, int col, Brush background, Pen pen, Geometry geometry, double imageWidth, int rowSpan, int colSpan)
             where T : FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                return container.AddGeometry<T>(chain.Item2, row, col, background, pen, geometry, imageWidth, rowSpan, colSpan);
            }));
            return chain;
        }

        /// <summary>
        /// Show Grid Lines on the Composite's Grid.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <returns></returns>
        public static InnerChain<T> ShowGridLinesOnGridComposite<T>(this InnerChain<T> chain)
      where T : System.Windows.Controls.Grid
        {
            chain.Item3.Add(((container) =>
            {
                return container.ShowGridLinesOnGridComposite<T>(chain.Item1);
            }));
            return chain;
        }

        /// <summary>
        ///  Modify Child K at Row X and Column Y Via Action
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="actionToModifyK"></param>
        /// <returns></returns>
        public static InnerChain<T> ModifyAtXY<K, T>(this InnerChain<T> chain, int row, int column, Action<K> actionToModifyK)
            where K : FrameworkElement
            where T : FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                T source = container.GetTFromChildContentControl<T>();
                
                IComposite icomp = SettingsManager.GetIComposite<T>(source);

                K childAtXY = (K)icomp.Get<K, T>(container, row, column);
                
                actionToModifyK(childAtXY);

                return container;
            }));

            return chain;
        }

        /// <summary>
        ///  Set Selector Class Name on Child K at Row X and Column Y
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="actionToModifyK"></param>
        /// <returns></returns>
        public static InnerChain<T> SetSelectorClassAtXY<K, T>(this InnerChain<T> chain, int row, int column, FasterWPF.SettingsManager.SelectorPosition position, string newSelectorClassName)
            where K : FrameworkElement
            where T : FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                T source = container.GetTFromChildContentControl<T>();

                IComposite icomp = SettingsManager.GetIComposite<T>(source);

                K childAtXY = (K)icomp.Get<K, T>(container, row, column);

                childAtXY.UpdateSelectorClass(position, newSelectorClassName);

                return container;
            }));

            return chain;
        }        
        
        /// <summary>
        /// Set MouseOverColor on Composite's Container, e.g. if GridComposite this would be a Grid
        /// </summary>
        /// <typeparam name="C"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="brush"></param>
        /// <returns></returns>
        public static InnerChain<T> SetMouseOverColorOnContainer<C, T>(this InnerChain<T> chain, Brush brush)
            where C: FrameworkElement
            where T: FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                container.SetMouseOverColorOnContainer<C, T>(brush);
                return container;
            }));

            return chain;
        }

        /// <summary>
        /// Set Background Color on Composite's Container, e.g. if GridComposite this would be a Grid
        /// </summary>
        /// <typeparam name="C"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="brush"></param>
        /// <returns></returns>
        public static InnerChain<T> SetColorOnContainer<C, T>(this InnerChain<T> chain, Brush brush)
            where C : FrameworkElement
            where T : FrameworkElement
        {
            chain.Item3.Add(((container) =>
            {
                container.SetColorOnContainer<C, T>(brush);
                return container;
            }));

            return chain;
        }

        #endregion
        
        #region AddComposite

        public static Border AddComposite<T, K>(this T chain, string key, K args, object settings, Action<ContentControl> addUIElementsAction)
    where T : FrameworkElement
        {
            Tuple<SelectionChangedEventHandler, Predicate<T>> mbeTupleS;
            FrameworkElement rowToAdd;
            commonAddComposite<T>(chain, key, addUIElementsAction, settings, out mbeTupleS, out rowToAdd);
            
            var dispDict = chain.GetDisposablesDictionary<T>();
            if (!dispDict.ContainsKey("SelectionChanged")) //only apply once
            {
                //apply if delegate and predicate aren't null
                chain.setSelectionChanged<T>(mbeTupleS.Item1, mbeTupleS.Item2);
            }

            IParent currentCompositeParent = chain.GetSetting<T, IParent>("IParent");
            currentCompositeParent.Add<K>(chain, key, args, (Border)rowToAdd);
            return (Border)rowToAdd;
        }

        public static Border AddComposite<T, K>(this T chain, string key, K args, Action<ContentControl> addUIElementsAction)
    where T : FrameworkElement
        {
            Tuple<SelectionChangedEventHandler, Predicate<T>> mbeTupleS;
            FrameworkElement rowToAdd;
            commonAddComposite<T>(chain, key, addUIElementsAction, null, out mbeTupleS, out rowToAdd);

            var dispDict = chain.GetDisposablesDictionary<T>();
            if (!dispDict.ContainsKey("SelectionChanged"))
            {
                chain.setSelectionChanged<T>(mbeTupleS.Item1, mbeTupleS.Item2);
            }

            IParent currentComposite = chain.GetSetting<T, IParent>("IParent");
            currentComposite.Add<K>(chain, key, args, (Border)rowToAdd);
            return (Border)rowToAdd;
        }

        private static void commonAddComposite<T>(T chain, string key, Action<ContentControl> addUIElementsAction, object settings, out Tuple<SelectionChangedEventHandler, Predicate<T>> mbeTupleS, out FrameworkElement rowToAdd) where T : FrameworkElement
        {
            mbeTupleS = getSelectionChangedDelegateFromSettings<T>(chain);
            Tuple<MouseButtonEventHandler, Predicate<Border>> mbeTuple = getDoubleClickDelegateFromSettings<T>(chain);
            Tuple<MouseButtonEventHandler, Predicate<Border>> mbeTupleX = getSingleClickDelegateFromSettings<T>(chain);
            
            //Wrap in Border - Create ContentControl - if Grid, Add Grid
             ContentControl cc = CommonExt.Create<T, ContentControl>(chain);
             IComposite icomp = SettingsManager.GetIComposite<T>(chain);
             cc.Tag = chain;

             icomp.AddCompositeToContentControl(chain, cc, settings);
             addUIElementsAction(cc);

             rowToAdd = (CommonExt.wrapInBorder(chain, cc, key)
                        .setDoubleClick(key, mbeTuple.Item1, mbeTuple.Item2)
                        .setSingleClick(key, mbeTupleX.Item1, mbeTupleX.Item2));
        }

        #endregion

        #region Get Text, Image, Element<T>, or Parent Container

        /// <summary>
        /// Get TextBlock Child from a Parent T. This is NOT meant to be called from a Composite (aka Border) but from the Parent T.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public static TextBlock GetTextBlock<T>(this T chain, string key, int row, int column)
               where T : FrameworkElement
        {
            if (chain.Tag == null)
            {
                throw new Exception("Error calling GetTextBlock! This must be called from a Parent T.");
            }

            //*******************************

            //NEED TO CHANGE THIS TO TRYGETVALUE INSTEAD to allow returning NULL IF KEY NOT FOUND IN DICT

            //*******************************

            TextBlock value = (TextBlock)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key +"_" + row + "_" + column];
            return value;
        }

        public static Image GetImage<T>(this T chain, string key, int row, int column)
               where T : FrameworkElement
        {
            Image value = (Image)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key +
"_" + row + "_" + column];
            return value;
        }
        
        public static Image GetImage<T>(this Border border, int row, int column)
             where T : FrameworkElement
        {
            ContentControl cc = (ContentControl)(border.Child);
            Image txb = cc.GetElement<Image, T>(row, column);

            return txb;
        }

        public static string GetText<T>(this Border border, int row, int column)
            where T : FrameworkElement
        {
            ContentControl cc = (ContentControl)(border.Child);
            TextBlock txb = cc.GetElement<TextBlock, T>(row, column);

            return txb.Inlines.FirstInline.Cast<System.Windows.Documents.Run>().Text.Trim().ToString();
        }

        public static string GetText<T>(this ContentControl chain, int row, int column)
            where T : FrameworkElement
        {
            TextBlock txb = GetElement<TextBlock, T>(chain, row, column);

            string returnedObject = null;
            if (txb != null)
            {
                returnedObject =
txb.Inlines.FirstInline.Cast<System.Windows.Documents.Run>().Text.Trim().ToString();
            }

            return returnedObject;
        }

        public static K GetElement<K, T>(this ContentControl chain,
int row, int column) where K : UIElement
            where T: FrameworkElement
        {
            K label = default(K);

            if (chain != null)
            {
                T lbx = (T)chain.GetParentFromContentControlOfComposite<T>();
                IComposite icomp = SettingsManager.GetIComposite<T>(lbx);
                label = icomp.Get<K, T>(chain, row, column);
            }
            return label;
        }

        public static FrameworkElement GetFrameworkElement<T>(this ContentControl chain, int row, int column)
            where T : FrameworkElement
        {
            FrameworkElement label = null;

            if (chain != null)
            {
                T lbx = (T)chain.GetParentFromContentControlOfComposite<T>();
                IComposite icomp = SettingsManager.GetIComposite<T>(lbx);
                label = icomp.Get<FrameworkElement, T>(chain, row, column);
            }
            return label;
        }

        /// <summary>
        /// Get Parent from the internal ContentControl of a composite. NOT meant to be called from derived Types (Child Elements)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="childElement"></param>
        /// <returns></returns>
        public static T GetParentFromContentControlOfComposite<T>(this ContentControl chain)
    where T : FrameworkElement
        {
            return (T)chain.Tag;
        }

        #endregion

        #region Methods to Get Text Run by Row-Column, EventArg or Content Control

        public static string GetTextRun(this MouseButtonEventArgs e)
        {
            string retVal = String.Empty;

            if (e.OriginalSource is System.Windows.Documents.Run)
            {
                retVal = e.OriginalSource.Cast<Run>().Text.Trim().ToString();
            }

            return retVal;
        }

        public static List<string> GetTextRuns<C, T>(this ContentControl c)
            where C : FrameworkElement
            where T : FrameworkElement
        {
            List<string> listStr = new List<string>();

            c.getRuns<C, T>().ForEach(s =>
            {
                listStr.Add(s.ToString());
            });

            return listStr;
        }

        public static List<string> GetTextRuns<C, T>(this MouseButtonEventArgs e, object sender)
                where C : FrameworkElement
                where T : FrameworkElement
        {
            List<string> listStr = new List<string>();

            sender.Cast<Border>().Child.Cast<ContentControl>().getRuns<C, T>().ForEach(s =>
            {
                listStr.Add(s.ToString());
            });

            return listStr;
        }

        private static List<string> getRuns<C, T>(this ContentControl sender)
                    where C : FrameworkElement
                    where T : FrameworkElement
        {
            List<string> lines = new List<string>();

            T lbx = (T)sender.GetParentFromContentControlOfComposite<T>();
            
            IComposite icomp = SettingsManager.GetIComposite<T>(lbx);
            C container = icomp.GetContainer<C>(sender.Parent as Border);

            foreach (UIElement innerLine in icomp.GetChildren(container))
            {
                if (innerLine is TextBlock)
                {
                    lines.Add(innerLine.Cast<TextBlock>().Inlines.FirstInline.Cast<System.Windows.Documents.Run>().Text.Trim().ToString());
                }
            }

            return lines;
        }

        #endregion

        #region Remove and RemoveByKey

        /// <summary>
        /// Removes all child Composites from IParent. NOTE: Call DisposeEventsOnAllParents prior to calling RemoveAll in order to unsubscribe events (to prevent memory leaks.)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        public static void RemoveAll<T>(this T chain)
            where T: FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();

            List<string> helper = new List<string>();

            //foreach (string key in orderedKeyList)
            //{
            //    helper.Add(key);
            //}

            for (int i = orderedKeyList.Count - 1; i >= 0; i--)
            {
                helper.Add(orderedKeyList[i]);
            }

            //helper.Reverse();

            foreach (string keyH in helper)
            {
                chain.RemoveByKey(keyH);
            }
        }

        /// <summary>
        /// Removes child Composite from IParent by key (e.g. guid). NOTE: If Composite being removed itself contains an IParent, call DisposeEventsOnAllParents on that internal IParent prior to calling RemoveByKey in order to unsubscribe events (to prevent memory leaks.)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        public static void RemoveByKey<T>(this T chain, string key)
            where T: FrameworkElement
        {
            var settings = chain.GetSettingsDictionary();

            //1. SETTINGS DICTIONARY - do NOT remove settings. These are independent. If you remove a Composite and then re-add it, the settings should still be alive to be applied to the re-added or new Composite

            //Remove matching row from RowDictionary
            //REMOVE_FROM_DICTIONARY BOOKMARK - 2. COMPOSITE_LOOKUP DICTIONARY
            Border border = GetCompositeFromCompositeLookupDictionary(chain, key);
            var borderDictionary = CommonExt.GetCompositeLookupDictionary(chain);
            borderDictionary.Remove(key);

            //Remove matching items from ChildLookupDictionary
            //REMOVE_FROM_DICTIONARY BOOKMARK - 3. CHILD_LOOKUP DICTIONARY
            List<string> keysToRemove = GetChildKeysFromComposite(chain, key);
            var keyDictionary = GetChildLookupDictionary(chain);

            foreach (var k in keysToRemove)
            {
                keyDictionary.Remove(k);
            }

            //Remove matching keyed events from Disposables Dictionary
            //REMOVE_FROM_DICTIONARY BOOKMARK - 4. DISPOSABLES DICTIONARY - only remove the events tied to a Border key. To remove all Child-related events, call DisposeEventsOnAllParents (on the Composite) prior to calling RemoveByKey
            UnsubscribeMouseDoubleClickOnBorderByKey(chain, key);
            UnsubscribeMouseSingleClickOnBorderByKey(chain, key);
            UnsubscribeBorderEventsByKey<T>(chain, key);
            UnsubscribeContainerEventsByKey<T>(chain, key);
            UnsubscribeBothChildAndBorderEventsByKey<T>(chain, key);

            //6. ATTACHED PROPERTIES DICTIONARY - no addition by key at this time so no need to remove!  besides this is like settings, applies to if you were to re-add the removed item so may want to retain? 
            //["AttachedPropertiesDict"] Dictionary
            //7. ATTACHED PROPERTIES BY ROWCOL DICTIONARY - no addition by key at this time so no need to remove!  besides this is like settings, applies to if you were to re-add the removed item so may want to retain? 
            //["AttachedPropertiesByRowColDict"] Dictionary

            //Remove key from OrderedKeyList
            //REMOVE_FROM_DICTIONARY BOOKMARK - 5. ORDERED KEY LIST
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            orderedKeyList.Remove(key);

            IParent currentComposite = chain.GetSetting<T, IParent>("IParent");
            currentComposite.Remove(chain, key, border);  //Remove from Parent Container
        }

        #endregion

        #region Update Text and Images

        public static T UpdateTextBlocks<T>(this T chain, int row, int column, Action<TextBlock> updateAction) where T : FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            string row_col = "_" + row + "_" + column;
       
            foreach (string key in orderedKeyList)
            {
                TextBlock value = (TextBlock)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key + row_col];
                updateAction(value);
            }

            return chain;
        }

        public static T UpdateViaStyleByKey<K, T>(this T chain, string key, int row, int column, Type basedOnType, DependencyProperty dp, object newValue) where T : FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            string row_col = "_" + row + "_" + column;

            foreach (string key1 in orderedKeyList)
            {
                if (key1 == key)
                {
                    K value = (K)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key1 + row_col];
                    StyleExt.SetStyle(chain as FrameworkElement, basedOnType, dp, newValue);
                }
            }

            return chain;
        }

        public static T UpdateViaStyle<K, T>(this T chain, int row, int column, Type basedOnType, DependencyProperty dp, object newValue) where T : FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            string row_col = "_" + row + "_" + column;

            foreach (string key1 in orderedKeyList)
            {
                K value = (K)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key1 + row_col];
                StyleExt.SetStyle(chain as FrameworkElement, basedOnType, dp, newValue);
            }

            return chain;
        }

        public static T Update<K, T>(this T chain, int row, int column, Action<K> updateAction) where T : FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            string row_col = "_" + row + "_" + column;

            foreach (string key1 in orderedKeyList)
            {
                K value = (K)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key1 + row_col];
                updateAction(value);
            }

            return chain;
        }

        public static T UpdateByKey<K, T>(this T chain, string key, int row, int column, Action<K> updateAction) where T : FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            string row_col = "_" + row + "_" + column;

            foreach (string key1 in orderedKeyList)
            {
                if (key1 == key)
                {
                    K value = (K)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key1 + row_col];
                    updateAction(value);
                }
            }

            return chain;
        }

        /// <summary>
        /// Updates a range of TextBlocks at the given row-column cell position beginning at rowStart which is zero-based.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="rowStart"></param>
        /// <param name="count"></param>
        /// <param name="updateAction"></param>
        /// <returns></returns>
        public static T UpdateTextBlocks<T>(this T chain, int row, int column, int rowStart, int count, Action<TextBlock> updateAction) where T : FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            string row_col = "_" + row + "_" + column;

            int k = rowStart;
            int j = 0;
            int counter = 0;

            foreach (string key in orderedKeyList)
            {
                if ((j == k) && counter < count)
                {
                    TextBlock value = (TextBlock)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key + row_col];
                    updateAction(value);
                    k++;
                    counter++;
                }

                j++;
            }

            return chain;
        }

        public static T UpdateImages<T>(this T chain, int row, int column, Action<Image> updateAction)
             where T : FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            string row_col = "_" + row + "_" + column; 

            foreach (string key in orderedKeyList)
            {
                Image value = (Image)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key +
row_col];
                updateAction(value);
            }

            return chain;
        }

        public static T UpdateImages<T>(this T chain, int row, int column, int rowStart, int count, Action<Image> updateAction) where T : FrameworkElement
        {
            List<String> orderedKeyList = chain.GetOrderedKeyList();
            string row_col = "_" + row + "_" + column; 

            int k = rowStart;
            int j = 0;
            int counter = 0;

            foreach (string key in orderedKeyList)
            {
                if ((j == k) && counter < count)
                {
                    Image value = (Image)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key +
    row_col];
                    updateAction(value);
                    k++;
                    counter++;
                }

                j++;
            }

            return chain;
        }
                 
        /// <summary>
        /// Update a TextBlock Located in a Container by the Current Text Value of the TextBlock. This is meant to be a one-for-one update.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        /// <returns></returns>
        public static TextBlock UpdateTextFoundByText<T>(this T chain, string key, string oldValue, string newValue)
            where T : FrameworkElement
        {
            TextBlock value = (TextBlock)Selectors.Select.SelectChildFrameworkElementsOnly(chain, false).Where(fe => { bool tempResult = false; if (fe is TextBlock) { if ((fe as TextBlock).GetText() == oldValue) { tempResult = true; } } else { tempResult = false; } return tempResult; }).FirstOrDefault();

            if (value != null)
            {
                value.Inlines.FirstInline.Cast<System.Windows.Documents.Run>().Text = newValue;
            }

            return value;
        }

        /// <summary>
        /// Update a Label Located in a Container by the Current Content Value of the Label. This is meant to be a one-for-one update.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        /// <returns></returns>
        public static Label UpdateLabelFoundByContent<T>(this T chain, string key, string oldValue, string newValue)
            where T : FrameworkElement
        {
            Label value = (Label)Selectors.Select.SelectChildFrameworkElementsOnly(chain, false).Where(fe => { bool tempResult = false; if (fe is Label) { if ((fe as Label).Content == oldValue) { tempResult = true; } } else { tempResult = false; } return tempResult; }).FirstOrDefault();

            value.Content = newValue;

            return value;
        }

        /// <summary>
        /// Find a Label Located in a Container by the Current Content Value of the Label. This is meant to return only the FirstOrDefault value located.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <param name="oldValue"></param>
        /// <returns></returns>
        public static Label FindLabelByContent<T>(this T chain, string key, string oldValue)
            where T : FrameworkElement
        {
            Label value = Selectors.Select.SelectChildFrameworkElementsOnly(chain, false).Where(fe => { bool tempResult = false; if (fe is Label) { if ((fe as Label).Content == oldValue) { tempResult = true; } } else { tempResult = false; } return tempResult; }).FirstOrDefault() as Label;

            return value;
        }

        /// <summary>
        /// Find a TextBlock Located in a Container by the Current Text Value of the TextBlock. This is meant to return only the FirstOrDefault value located.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <param name="oldValue"></param>
        /// <returns></returns>
        public static TextBlock FindTextBlockByText<T>(this T chain, string key, string oldValue)
            where T : FrameworkElement
        {
            TextBlock value = Selectors.Select.SelectChildFrameworkElementsOnly(chain, false).Where(fe => { bool tempResult = false; if (fe is TextBlock) { if ((fe as TextBlock).GetText() == oldValue) { tempResult = true; } } else { tempResult = false; } return tempResult; }).FirstOrDefault() as TextBlock;

            return value;
        }        
        
        /// <summary>
        /// Find Labels Located in a Container by the Current Content Value of each Label.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <param name="contentToFind"></param>
        /// <returns></returns>
        public static List<Label> FindLabelsByContent<T>(this T chain, string key, string contentToFind)
            where T : FrameworkElement
        {
            List<Label> labelList = new List<Label>();

            var values = Selectors.Select.SelectChildFrameworkElementsOnly(chain, false).Where(fe => { bool tempResult = false; if (fe is Label) { if ((fe as Label).Content == contentToFind) { tempResult = true; } } else { tempResult = false; } return tempResult; });
            foreach (FrameworkElement fe in values)
            {
                labelList.Add(fe as Label);
            }
            return labelList;
        }

        /// <summary>
        /// Find TextBlocks Located in a Container by the Current Text Value of each TextBlock.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="chain"></param>
        /// <param name="key"></param>
        /// <param name="textToFind"></param>
        /// <returns></returns>
        public static List<TextBlock> FindTextBlocksByText<T>(this T chain, string key, string textToFind)
            where T : FrameworkElement
        {
            List<TextBlock> textBlockList = new List<TextBlock>();

            var values = Selectors.Select.SelectChildFrameworkElementsOnly(chain, false).Where(fe => { bool tempResult = false; if (fe is TextBlock) { if ((fe as TextBlock).GetText() == textToFind) { tempResult = true; } } else { tempResult = false; } return tempResult; });
            foreach (FrameworkElement fe in values)
            {
                textBlockList.Add(fe as TextBlock);
            }
            return textBlockList;
        }

        public static TextBlock UpdateTextByKey<T>(this T chain, string key, int row, int column, string newValue)
            where T : FrameworkElement
        {
            TextBlock value = (TextBlock)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key +
"_" + row + "_" + column];
                      
            value.Inlines.FirstInline.Cast<System.Windows.Documents.Run>().Text = newValue;

            return value;
        }

        public static void UpdateImageByKey<T>(this T chain, string key, int row, int column, string imageUri, UriKind uriKind) where T : FrameworkElement
        {
            Image value = (Image)((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key +
"_" + row + "_" + column];

            var uriSource = new Uri(imageUri, uriKind);
            value.Source = new BitmapImage(uriSource);
        }
        
        public static void UpdateFontAtKeyByStyleKey<T>(this T chain, string styleKey, string key, int row, int column)
             where T : FrameworkElement
        {
            object UIElementAtRowCol = ((Dictionary<string, object>)((Dictionary<string, object>)chain.Tag)["ChildLookup"])[key +
"_" + row + "_" + column];
            if (UIElementAtRowCol is TextBlock)
            {
                FontSettings fs = SettingsManager.GetSetting<T, FontSettings>(chain, styleKey = styleKey + "Font");
                FontExt.ApplyFontSettings(fs, new FontFamily(fs.FontFamily), (TextBlock)UIElementAtRowCol);
            }
        }

        #endregion
                
        #region Create Border-ContentControl Container for all Child Items

        public static Border CreateBorder<T>(T source, double width, double height, Brush brush, Thickness thickness, Visibility visibility,
            CornerRadius cornerRadius, Thickness padding) where T: FrameworkElement
        {
            Border b = new Border();
            b.Width = width;
            b.Height = height;
            b.BorderBrush = brush;
            b.BorderThickness = thickness;
            b.Visibility = visibility;
            b.Background = Brushes.Transparent;
            b.CornerRadius = cornerRadius;
            b.Padding = padding;
            return b;
        }

        public static K Create<T, K>(T parent)
            where T : FrameworkElement
            where K : ContentControl
        {
            K myNewObject = default(K);
            myNewObject = Activator.CreateInstance<K>();

            return myNewObject;
        }

        public static T Create<T>(this object chain)
        {
            T newValue = default(T);
            newValue = Activator.CreateInstance<T>();
            return newValue;
        }               

        public static T GetContent<T>(this ContentControl chain)
        {
            T newValue = ((T)chain.Content);
            return newValue;
        }

        //NOTE: for easy access, I store a handle to the Parent source T on the tag of the Child's Content Control
        private static ContentControl SetContent<T, K>(this ContentControl
chain, T source)
    where T : FrameworkElement
        {
            K newValue = default(K);

            newValue = Activator.CreateInstance<K>();
            chain.Tag = source;

            chain.Content = newValue;

            return chain;
        }
               
        private static FrameworkElement wrapInBorder<T>(T source,
ContentControl chain, string key)
                where T : FrameworkElement
        {
            Dictionary<string, object> settings = new Dictionary<string, object>();
            FrameworkElement result = null;

            if (source.Tag != null && (source.ContainsSetting("Border")))
            {
                settings = source.GetSettingsDictionary();
                Border storedBorder = settings["Border"].Cast<Border>();
                BorderSettings brushAndThickness = settings["BorderSettings"].Cast<BorderSettings>();

                storedBorder.Width = brushAndThickness.Width;       
                storedBorder.Height = brushAndThickness.Height;        
                storedBorder.BorderBrush = brushAndThickness.BorderBrush;  
                storedBorder.BorderThickness = brushAndThickness.BorderThickness;
                storedBorder.CornerRadius = brushAndThickness.CornerRadius;
                storedBorder.Padding = brushAndThickness.Padding;

                Border clonedBorder = CommonExt.CreateBorder(source, storedBorder.Width, storedBorder.Height, storedBorder.BorderBrush, storedBorder.BorderThickness, storedBorder.Visibility, storedBorder.CornerRadius, storedBorder.Padding);

                if (settings.ContainsKey("UseLayoutRounding"))
                {
                    clonedBorder.UseLayoutRounding = (bool)settings["UseLayoutRounding"];
                }

                if (settings.ContainsKey("Padding"))
                {
                    clonedBorder.Cast<Border>().Padding = settings["Padding"].Cast<Thickness>();
                }

                clonedBorder.Child = chain;

                //ADD_TO_DICTIONARY BOOKMARK - 2. CompositeLookup
                source.GetCompositeLookupDictionary().Add(key, clonedBorder);

                //ADD_TO_DICTIONARY BOOKMARK - 5. OrderedKeyList
                source.GetOrderedKeyList().Add(key);

                result = (FrameworkElement)clonedBorder;
            }
            else
            {
                result = (FrameworkElement)chain;
            }

            return result;
        }

        #endregion
        
    }//end of class
}//end of namespace
